import numpy as np
from itertools import product
import pandas as pd

class ProductionDecisionModel:
    def __init__(self):
        # 决策变量: x1,x2,x3,x4 ∈ {0,1}
        # x1: 零件1是否检测 (1=检测, 0=不检测)
        # x2: 零件2是否检测 (1=检测, 0=不检测)
        # x3: 成品是否检测 (1=检测, 0=不检测)
        # x4: 不合格成品是否拆解 (1=拆解, 0=不拆解)
        self.decision_vars = ['x1', 'x2', 'x3', 'x4']
        
    def set_parameters(self, p1, p2, pc, c1b, c2b, c1t, c2t, cpt, ca, cd, ce, R):
        """设置参数"""
        self.p1, self.p2, self.pc = p1, p2, pc  # 次品率
        self.c1b, self.c2b = c1b, c2b  # 购买成本
        self.c1t, self.c2t, self.cpt = c1t, c2t, cpt  # 检测成本
        self.ca, self.cd, self.ce = ca, cd, ce  # 装配、拆解、换货成本
        self.R = R  # 市场售价
    
    def calculate_expected_revenue(self, x1, x2, x3, x4):
        """
        计算预期收入 S = R ⋅ (1 - p₁x₁) ⋅ (1 - p₂x₂) ⋅ (1 - p_c x₃) + x₄ ⋅ (1 - p₁x₁) ⋅ (1 - p₂x₂) ⋅ p_c ⋅ [c₁b(1 - p₁) + c₂b(1 - p₂)]
        第一部分：销售合格成品的收入（考虑检测决策）
        第二部分：拆解回收零配件的收入
        """
        # 第一部分：销售合格成品的收入
        # 考虑检测决策的影响
        S_part1 = self.R * (1 - self.p1 * x1) * (1 - self.p2 * x2) * (1 - self.pc * x3)
        
        # 第二部分：拆解回收零配件的收入
        # 只有当选择拆解(x4=1)时才产生此收入
        # 拆解的是不合格成品，回收的是合格零件
        S_part2 = x4 * (1 - self.p1 * x1) * (1 - self.p2 * x2) * self.pc * (self.c1b * (1 - self.p1) + self.c2b * (1 - self.p2))
        
        S = S_part1 + S_part2
        return S
    
    def calculate_total_cost(self, x1, x2, x3, x4):
        """
        根据图片中的目标函数计算总成本C
        """
        # 1. 购买成本: c₁b + c₂b
        purchase_cost = self.c1b + self.c2b
        
        # 2. 检测成本: x₁c₁t + x₂c₂t + x₃c_pt
        inspection_cost = x1 * self.c1t + x2 * self.c2t + x3 * self.cpt
        
        # 3. 装配成本: c_a(1 - p₁x₁)(1 - p₂x₂)
        assembly_cost = self.ca * (1 - self.p1 * x1) * (1 - self.p2 * x2)
        
        # 4. 拆解成本期望值
        # 对检测出的不合格成品进行拆解: x₃ ⋅ p_c ⋅ x₄ ⋅ c_d
        disassembly_cost_inspected = x3 * self.pc * x4 * self.cd
        
        # 对退回的不合格成品进行拆解: (1 - x₃) ⋅ [1 - (1 - p₁x₁)(1 - p₂x₂)(1 - p_c)] ⋅ x₄ ⋅ c_d
        # 只有当成品不检测(x3=0)时，才可能有用户退回的不合格品
        defect_prob_returned = (1 - x3) * (1 - (1 - self.p1 * x1) * (1 - self.p2 * x2) * (1 - self.pc)) * x4 * self.cd
        disassembly_cost_returned = defect_prob_returned
        
        # 5. 调换损失期望值: c_e ⋅ (1 - x₃)[1 - (1 - p₁x₁)(1 - p₂x₂)(1 - p_c)]
        # 只有当成品不检测(x3=0)时，才可能有换货损失
        replacement_loss = self.ce * (1 - x3) * (1 - (1 - self.p1 * x1) * (1 - self.p2 * x2) * (1 - self.pc))
        
        # 总成本（不包含回收价值，因为回收价值现在是收入的一部分）
        total_cost = (purchase_cost + inspection_cost + assembly_cost + 
                     disassembly_cost_inspected + disassembly_cost_returned + 
                     replacement_loss)
        
        return total_cost, {
            'purchase_cost': purchase_cost,
            'inspection_cost': inspection_cost,
            'assembly_cost': assembly_cost,
            'disassembly_cost_inspected': disassembly_cost_inspected,
            'disassembly_cost_returned': disassembly_cost_returned,
            'replacement_loss': replacement_loss
        }
    
    def calculate_profit(self, x1, x2, x3, x4):
        """计算利润 W = S - C"""
        # 预期收入（包含回收价值）
        revenue = self.calculate_expected_revenue(x1, x2, x3, x4)
        
        # 总成本
        total_cost, cost_details = self.calculate_total_cost(x1, x2, x3, x4)
        
        # 利润
        profit = revenue - total_cost
        
        return profit, revenue, total_cost, cost_details
    
    def find_optimal_decision(self):
        """寻找最优决策"""
        max_profit = float('-inf')
        optimal_decision = None
        optimal_details = None
        
        # 枚举所有决策组合
        for x1, x2, x3, x4 in product([0, 1], repeat=4):
            profit, revenue, total_cost, cost_details = self.calculate_profit(x1, x2, x3, x4)
            
            if profit > max_profit:
                max_profit = profit
                optimal_decision = (x1, x2, x3, x4)
                optimal_details = {
                    'profit': profit,
                    'revenue': revenue,
                    'total_cost': total_cost,
                    'cost_details': cost_details
                }
        
        return optimal_decision, optimal_details

def print_all_decisions(situation_num, params):
    """打印所有16种决策组合"""
    print(f"\n=== 情形{situation_num} 所有决策组合 ===")
    print(f"参数: p1={params['p1']:.1%}, p2={params['p2']:.1%}, pc={params['pc']:.1%}")
    print(f"成本: c1t={params['c1t']}, c2t={params['c2t']}, cpt={params['cpt']}, ce={params['ce']}")
    print(f"{'决策':>8} {'零件1':>6} {'零件2':>6} {'成品':>6} {'拆解':>6} {'利润':>10} {'收入':>10} {'总成本':>10} {'购买':>8} {'检测':>8} {'装配':>8} {'拆解':>8} {'回收':>8} {'换货':>8}")
    print("-" * 140)
    
    model = ProductionDecisionModel()
    model.set_parameters(**params)
    
    all_profits = []
    all_data = []
    for x1, x2, x3, x4 in product([0, 1], repeat=4):
        profit, revenue, total_cost, cost_details = model.calculate_profit(x1, x2, x3, x4)
        all_profits.append(profit)
        
        decision_str = f"{x1}{x2}{x3}{x4}"
        print(f"{decision_str:>8} {'是' if x1 else '否':>6} {'是' if x2 else '否':>6} {'是' if x3 else '否':>6} {'是' if x4 else '否':>6} "
              f"{profit:>10.2f} {revenue:>10.2f} {total_cost:>10.2f} {cost_details['purchase_cost']:>8.2f} {cost_details['inspection_cost']:>8.2f} "
              f"{cost_details['assembly_cost']:>8.2f} {cost_details['disassembly_cost_inspected']+cost_details['disassembly_cost_returned']:>8.2f} "
              f"{'N/A':>8} {cost_details['replacement_loss']:>8.2f}")
        
        # 收集数据用于Excel导出
        all_data.append({
            '情形': situation_num,
            '决策': decision_str,
            '零件1检测': '是' if x1 else '否',
            '零件2检测': '是' if x2 else '否',
            '成品检测': '是' if x3 else '否',
            '拆解': '是' if x4 else '否',
            '利润': profit,
            '收入': revenue,
            '总成本': total_cost,
            '购买成本': cost_details['purchase_cost'],
            '检测成本': cost_details['inspection_cost'],
            '装配成本': cost_details['assembly_cost'],
            '拆解成本': cost_details['disassembly_cost_inspected'] + cost_details['disassembly_cost_returned'],
            '换货损失': cost_details['replacement_loss']
        })
    
    # 找到最优决策
    max_profit = max(all_profits)
    optimal_indices = [i for i, profit in enumerate(all_profits) if profit == max_profit]
    
    print("-" * 140)
    print(f"最优决策:")
    for i, (x1, x2, x3, x4) in enumerate(product([0, 1], repeat=4)):
        if i in optimal_indices:
            decision_str = f"{x1}{x2}{x3}{x4}"
            print(f"  决策{decision_str}: 零件1{'是' if x1 else '否'}, 零件2{'是' if x2 else '否'}, 成品{'是' if x3 else '否'}, 拆解{'是' if x4 else '否'}")
    print(f"最大利润: {max_profit:.2f}")
    
    return max_profit, all_data

def export_to_excel(all_results_data, filename='企业生产决策分析.xlsx'):
    """导出所有结果到Excel文件"""
    # 创建DataFrame
    df = pd.DataFrame(all_results_data)
    
    # 创建Excel写入器
    with pd.ExcelWriter(filename, engine='openpyxl') as writer:
        # 写入详细数据
        df.to_excel(writer, sheet_name='详细决策数据', index=False)
        
        # 创建汇总表
        summary_data = []
        for situation_num in range(1, 7):
            situation_data = df[df['情形'] == situation_num]
            max_profit_row = situation_data.loc[situation_data['利润'].idxmax()]
            summary_data.append({
                '情形': situation_num,
                '最优决策': max_profit_row['决策'],
                '最大利润': max_profit_row['利润'],
                '预期收入': max_profit_row['收入'],
                '总成本': max_profit_row['总成本'],
                '零件1检测': max_profit_row['零件1检测'],
                '零件2检测': max_profit_row['零件2检测'],
                '成品检测': max_profit_row['成品检测'],
                '拆解': max_profit_row['拆解']
            })
        
        summary_df = pd.DataFrame(summary_data)
        summary_df.to_excel(writer, sheet_name='最优决策汇总', index=False)
        
        # 创建参数表
        params_data = {
            '情形': [1, 2, 3, 4, 5, 6],
            '零件1次品率': ['10%', '20%', '10%', '20%', '10%', '5%'],
            '零件2次品率': ['10%', '20%', '10%', '20%', '20%', '5%'],
            '成品次品率': ['10%', '20%', '10%', '20%', '10%', '5%'],
            '零件1检测成本': [2, 2, 2, 1, 8, 2],
            '零件2检测成本': [3, 3, 3, 1, 1, 3],
            '成品检测成本': [3, 3, 3, 2, 2, 3],
            '换货损失': [6, 6, 30, 30, 10, 10],
            '拆解成本': [5, 5, 5, 5, 5, 40]
        }
        params_df = pd.DataFrame(params_data)
        params_df.to_excel(writer, sheet_name='参数设置', index=False)
    
    print(f"\nExcel文件已导出: {filename}")
    print("包含以下工作表:")
    print("1. 详细决策数据 - 所有96种决策组合的详细信息")
    print("2. 最优决策汇总 - 6种情形的最优决策")
    print("3. 参数设置 - 各情形的参数配置")

if __name__ == "__main__":
    # 情形数据（根据图片中的表1）
    situations = {
        1: {'p1': 0.1, 'p2': 0.1, 'pc': 0.1, 'c1b': 4, 'c2b': 18, 'c1t': 2, 'c2t': 3, 'cpt': 3, 'ca': 6, 'cd': 5, 'ce': 6, 'R': 56},
        2: {'p1': 0.2, 'p2': 0.2, 'pc': 0.2, 'c1b': 4, 'c2b': 18, 'c1t': 2, 'c2t': 3, 'cpt': 3, 'ca': 6, 'cd': 5, 'ce': 6, 'R': 56},
        3: {'p1': 0.1, 'p2': 0.1, 'pc': 0.1, 'c1b': 4, 'c2b': 18, 'c1t': 2, 'c2t': 3, 'cpt': 3, 'ca': 6, 'cd': 5, 'ce': 30, 'R': 56},
        4: {'p1': 0.2, 'p2': 0.2, 'pc': 0.2, 'c1b': 4, 'c2b': 18, 'c1t': 1, 'c2t': 1, 'cpt': 2, 'ca': 6, 'cd': 5, 'ce': 30, 'R': 56},
        5: {'p1': 0.1, 'p2': 0.2, 'pc': 0.1, 'c1b': 4, 'c2b': 18, 'c1t': 8, 'c2t': 1, 'cpt': 2, 'ca': 6, 'cd': 5, 'ce': 10, 'R': 56},
        6: {'p1': 0.05, 'p2': 0.05, 'pc': 0.05, 'c1b': 4, 'c2b': 18, 'c1t': 2, 'c2t': 3, 'cpt': 3, 'ca': 6, 'cd': 40, 'ce': 10, 'R': 56}
    }
    
    print("=== 企业生产决策优化分析 ===")
    print("目标函数: max W = S - C")
    print("分析所有16种决策组合在6种情形下的表现")
    print("决策编码: x1x2x3x4 (0=否, 1=是)")
    print("=" * 140)
    
    results = {}
    all_results_data = []
    for situation_num, params in situations.items():
        max_profit, situation_data = print_all_decisions(situation_num, params)
        results[situation_num] = max_profit
        all_results_data.extend(situation_data)
    
    print(f"\n=== 各情形最大利润汇总 ===")
    for situation_num, max_profit in results.items():
        print(f"情形{situation_num}: {max_profit:.2f}")
    
    # 导出到Excel
    export_to_excel(all_results_data)
